/*! \defgroup settings Settings
*/

/*! \file settings.h
    \ingroup settings
    \brief This file contains declarations for global settings.
    \version 1.0

    Settings are stored in XML file 'settings.xml'. To access settings use g_Settings global varriable.
    User can access settings via SettingsDialog widget.
*/

#ifndef __DYNAMICVIEWSETTINGS_H
#define __DYNAMICVIEWSETTINGS_H

#include <QDomElement>
#include <QPainter>
#include <QFont>
#include <QVariant>

//#include "logmodel.h"
//#include "global.h"

class Settings;
class Aliases;
class TextStyle;
class StylePackage;
class SettingsDialog;
class StyleWidget;
class ColorComboBox;
class EnumAliasStyle;
class ItemStyleSettings;
class PropertyAliasStyle;
class ItemStyle;

/*! Global varriable for application settings.
    \ingroup settings
 */
extern ItemStyleSettings g_Settings;

/*! Global varriable for application skins directory.
    \ingroup settings
    \todo create class for such constants.
 */
extern QString g_Settings_skin_dir;

/*! \class TextStyle
    \ingroup settings
    \brief This class contains settings for the text painting.

    This class is designed to contain font and color settings for DebugTreeView items painting.
    Settings are stored in XML file 'settings.xml'. One instance corresponds to one 'style' tag.
    \warning This class is used to represent only 'style' elements. To access 'property' elements
        use class PropertyStyle.
 */
class TextStyle : public QObject
{
    Q_OBJECT

public:
    enum Type
    {
        TypeExclusiveStyle,
        TypePropertyStyle,
        TypeAliasStyle,
        TypeItemStyle
    };

    TextStyle();

    /*! Creates text style using XML element from 'settings.xml' file. */
    TextStyle(const QDomElement & element, TextStyle * parent = 0);

    virtual Type type() const = 0;

    /*! Returns text color. */
    QColor fgColor(bool native = false) const;
    void setFgColor(QColor color = QColor());

    /*! Returns text font family. */
    QString fontFamily(bool native = false) const;

    /*! Sets text font family. */
    void setFontFamily(const QString & family = QString());

    /*! Returns text font size. */
    int fontSize(bool native = false) const;

    /*! Sets font size. */
    void setFontSize(int size = -1);

    /*! Returns true if font is bold. Otherwise returns false. */
    Qt::CheckState bold(bool native = false) const;

    /*! Sets bold font property to \a bold. */
    void setBold(Qt::CheckState bold);

    /*! Returns true if font is italic. Otherwise returns false. */
    Qt::CheckState italic(bool native = false) const;

    /*! Sets italic font property to \a italic. */
    void setItalic(Qt::CheckState italic);

    /*! Returns true if font is underline. Otherwise returns false. */
    Qt::CheckState underline(bool native = false) const;

    /*! Sets underline font property to \a underline. */
    void setUnderline(Qt::CheckState underline);

    QFont font() const;

    QString description() const;
    void setDescription(const QString & description);

    static void adjustPainter( QPainter * painter, const TextStyle * style, int highlightFactor = 0 );

    virtual void toElement( QDomElement * element, QDomDocument * document );

    QString nodeLabel() const;
    void setNodeLabel( const QString & label );
    virtual void operator=( const TextStyle & style );

private:
    TextStyle * m_parent;
    QColor m_fgColor;
    QString m_fontFamily;
    int m_fontSize;
    Qt::CheckState m_bold;
    Qt::CheckState m_italic;
    Qt::CheckState m_underline;
    QString m_description;
    QString m_nodeLabel;
};

class ExclusiveTextStyle : public TextStyle
{
    Q_OBJECT

public:
    ExclusiveTextStyle();
    ExclusiveTextStyle(const QDomElement & element, ItemStyle * parent);
    TextStyle::Type type() const;
    QString name() const;
    void toElement( QDomElement * element, QDomDocument * document );

private:
    ItemStyle * m_parent;
    QString m_name;
};

/*! PropertyStyleBase * is declared to use it in QVariant. */
Q_DECLARE_METATYPE(TextStyle *);

class PropertyStyleBase : public TextStyle
{
    Q_OBJECT

public:
    /*! \enum Visibility
        Contains constants to indicate, whether property is shown or not in tree model.
     */
    enum Visibility
    {
        /*! Property is hidden. */
        Hidden    = 0,

        /*! Property value is visible, property label is hidden. */
        ValueOnly = 1,

        /*! Property value and property label are visible. */
        Visible   = 2
    };

    PropertyStyleBase();
    PropertyStyleBase(const QDomElement & element, TextStyle * parent = 0);

    /*! Returns property visibility. It indicates, whether property is shown or not in tree model. */
    Visibility visibility() const;

    /*! Sets visibility. */
    void setVisibility(Visibility visibility);
    void toElement( QDomElement * element, QDomDocument * document );
    virtual void operator=( const PropertyStyleBase & style );

private:
    Visibility m_visibility;
};

/*! PropertyStyleBase * is declared to use it in QVariant. */
Q_DECLARE_METATYPE(PropertyStyleBase *);

/*! \class PropertyStyle
    \ingroup settings
    \brief This class contains settings for the text painting.

    This class is designed to contain font, color and alias settings for DebugTreeView items painting.
    Settings are stored in XML file 'settings.xml'. One instance corresponds to one 'property' tag.
 */
class PropertyStyle : public PropertyStyleBase
{
    Q_OBJECT

public:
    /*! \enum Type
        Property types
     */
    enum Type
    {
        Undefined      = -1,
        Enum           = 0,
        String         = 1,
        DateTime       = 2,
        Integer        = 3,
        Boolean        = 4,
        Time           = 5,

        Form           = 16,
        Field          = 17,
        ActiveLink     = 18,
        Filter         = 19,
        Guide          = 20,
        ActionsList    = 21,
        AssignPairsMap = 22
    };

    PropertyStyle();

    /*! Creates property style using XML element 'property' from 'settings.xml' file. */
    PropertyStyle(const QDomElement & element, ItemStyle * parent);

    TextStyle::Type type() const;

    ItemStyle * parentStyle();

    /*! Returns property type. \sa Type */
    Type type();

    /*! Sets property type to \a type. \sa Type */
    void setType(Type type);

    /*! Returns property name. */
    QString name() const;

    /*! Sets property style name. */
    void setName(const QString & name);

    /*! Returns property label. This string is used to show it to user instead property name. */
    QString label() const;

    /*! Sets property label. */
    void setLabel(const QString & lable);

    /*! Returns separator. This string is drawn between property label and value. */
    QString separator() const;

    /*! Sets separator. */
    void setSeparator(const QString & separator);

    /*! Returns property style for special value. Used only for enum properties.
        \sa enumAliasStyles;
     */
    PropertyAliasStyle * styleForValue(const QVariant & value) const;

    /*! Returns property alias styles table.
        \sa styleForValue;
    */
    QList<PropertyAliasStyle *> aliasStyles() const;

    bool hasAliasStyles();

    /*! Returns true if this property has reference aliases to other styles. Otherwise returns false. */
    bool isTypeSelector();

    /*! Sets wjether property is type selector or not. */
    void setTypeSelector(bool isSelector);

    int order();

    void toElement( QDomElement * element, QDomDocument * document );

private:
    ItemStyle * m_parent;
    Type m_type;
    QString m_name;
    QString m_label;
    QString m_separator;
    bool m_isTypeSelector;
    int m_order;

    QList<PropertyAliasStyle *> m_aliasStyles;
};

typedef QList<PropertyStyle *> PropertyStyleList;

/*! \class PropertyAliasStyle
    \ingroup settings
*/
class ARSObjectPropertyStyle : public PropertyStyle
{
    Q_OBJECT

public:
    ARSObjectPropertyStyle( const QDomElement & element, ItemStyle * parent );

    bool isMultiline();
    QColor bgColor();
    void toElement( QDomElement * element, QDomDocument * document );

private:
    bool m_isMultiline;
    QColor m_bgColor;
};

/*! PropertyStyle * is declared to use it in QVariant. */
Q_DECLARE_METATYPE(PropertyStyle *);

/*! \class PropertyAliasStyle
    \ingroup settings
*/
class PropertyAliasStyle : public PropertyStyleBase
{
    Q_OBJECT

public:
    PropertyAliasStyle();

    /*! Constructor */
    PropertyAliasStyle( const QDomElement & element, PropertyStyle * parent );

    TextStyle::Type type() const;

    PropertyStyle * parentStyle();

    QVariant value();
    void setValue(const QVariant & value);

    QString alias();
    void setAlias(const QString & alias);

    /*! Returns type name corresponding to this propertyr value.
        \warning Only for 'alias' styles
    */
    QString referenceType();

    /*! Sets type name corresponding to this propertyr value. */
    void setReferenceType(const QString & type);

    void toElement( QDomElement *element, QDomDocument * document );

private:
    PropertyStyle * m_parent;
    QString m_alias;
    QString m_referenceType;
    QVariant m_value;
};

class ARSObjectPropertyAliasStyle : public PropertyAliasStyle
{
    Q_OBJECT

public:
    ARSObjectPropertyAliasStyle( const QDomElement & element, PropertyStyle * parent );
    QColor bgColor();

    void toElement( QDomElement *element, QDomDocument * document );

private:
    QColor m_bgColor;
};

/*! PropertyAliasStyle * is declared to use it in QVariant. */
Q_DECLARE_METATYPE(PropertyAliasStyle *);

/*! \class ItemStyle
    \ingroup settings
    \brief This class is designed to contain settings for one model item as a list of property styles.

    It is painting settings for one ARSExecItem object.
    Item styles are stored in a tree, that complitely repeates ARSExecItem classes hierarchy.
    Tree structure is necessary to get inherited propeties from the parent style.
*/
class ItemStyle : public TextStyle
{
    Q_OBJECT

public:
    enum ItemType
    {
        ExecutionModelItem = 0,
        ServerItem         = 1
    };

    enum PropertyOption
    {
        NativeOnly,
        IncludeInherited
    };

    ItemStyle();

    /*! Creates item style from \a element with parent item \a parent. */
    ItemStyle(const QDomElement & element, ItemStyle * parent = 0);

    TextStyle::Type type() const;

    ItemType itemType() const;

    /*! Returns property style named \a propertyName if exists. Otherwise returns 0. */
    PropertyStyle * propertyStyle(const QString & propertyName) const;

    /*! Returns property styles list.
        \warning inherited properties are not included to list.
        \todo redesign to PropertyStyle * propertyStyle();
     */
    PropertyStyleList propertyStyles(PropertyOption option = NativeOnly) const;

    static bool propertyStyleLessThan( PropertyStyle * style1, PropertyStyle * style2 );

    /*! Returns property styles count. */
    int propertyStylesCount() const;

    /*! Returns parent property style. */
    ItemStyle * parentStyle() const;

    /*! Returns children styles count. */
    int childStylesCount() const;

    /*! Returns children style at index \a index. */
    ItemStyle * childStyle(int index) const;

    /*! Returns item style name. It equals corresponding class name. */
    QString name() const;

    /*! Returns exclusive styles count. */
    int exclusiveStylesCount() const;

    /*! Returns children style at index \a index. */
    ExclusiveTextStyle * exclusiveStyle(int index) const;

    void toElement( QDomElement *element, QDomDocument * document );

private:
    ItemStyle * m_parent;
    QList<ItemStyle *> m_childStyles;
    PropertyStyleList m_propertyStyles;
    QList<ExclusiveTextStyle *> m_exclusiveStyles;
    QString m_name;
    ItemType m_itemType;
};

/*! ItemStyle * is declared to use it in QVariant. */
Q_DECLARE_METATYPE(ItemStyle *);

/*
class StylePackage : public ItemStyle
{
public:
    StylePackage(const QDomElement & element);

    TextStyle * defaultStyle() const;
    void setDefaultStyle(TextStyle * style);

private:
    TextStyle * m_defaultStyle;
    QList<TextStyle *> m_uniqueStyles;
};*/

/*! StylePackage * is declared to use it in QVariant. */
Q_DECLARE_METATYPE(StylePackage *);

/*! \class ItemStyle
    \ingroup settings
    \brief This class is designed to settings for one model item as a list of property styles.

    It is painting settings for one ARSExecItem object.
    Item styles are stored in a tree, that complitely repeates ARSExecItem classes hierarchy.
    Tree structure is necessary to get inherited propeties from the parent style.
*/
class ItemStyleSettings : public QObject
{
    Q_OBJECT

public:
    static const int maxRecentFilesCount = 10;

    /*! Creates empty ItemStyleSettings object. */
    ItemStyleSettings(QObject * parent = 0);

    /*! Reads settings from 'settings.xml' file. */
    bool readSettings();

    /*! Reads settings from 'settings.xml' file. */
    bool readStyleSettings();

    void saveStyleSettings();

    ItemStyle * itemStyle(const QString & className) const;

    QString fontFamily() const;
    int fontSize() const;

    /*! Reads settings from 'settings.xml' file. */
    PropertyStyle * propertyStyle(const QString & className, const QString & propertyName) const;

    /*! Returns top level item styles list. */
    QList<ItemStyle *> topLevelItemStyles();

//    QStringList recentFiles();
//    void appendRecentFile(const QString & fileName);

    QFont tableViewsFont() const;
    QString reportsCSS() const;

//signals:
//    void recentFilesListChanged();

private:
    /*! Reads settings from 'settings.xml' file. */
//    void readRecentFilesList();

    ItemStyle * findChildStyle( ItemStyle * style, const QString & name ) const;

    QList<TextStyle *> m_styles;
    QList<ItemStyle *> m_topLevelItemStyles;
//    QStringList m_recentFiles;
    QDomDocument m_styleDocument;
    QString m_reportsCSS;
};

#endif // __DYNAMICVIEWSETTINGS_H
